package com.bwie.controller;

import com.alibaba.fastjson.JSON;
import com.bwie.es.EsStadium;
import com.bwie.pojo.*;
import com.bwie.service.*;
import com.bwie.unit.FreemarkerUtil;
import com.bwie.unit.MessageVo;
import com.bwie.unit.R;
import com.rabbitmq.client.Channel;
import freemarker.template.TemplateException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.checkerframework.checker.guieffect.qual.UI;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("list")
public class StadiumController {

    @Autowired
    private StadiumService stadiumService;

    @Autowired
    private TypeService typeService;


    @Autowired
    private ImageService imageService;

    @Autowired
    private BookingService bookingService;

    @Autowired
    private LinkageService linkageService;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PostMapping("createEs")
    public R createEs(){
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(EsStadium.class);
        boolean exists = indexOperations.exists();
        if (exists){
            indexOperations.delete();
        }
        indexOperations.create();
        Document mapping = indexOperations.createMapping();
        indexOperations.putMapping(mapping);
        return R.OK();
    }

    @PostMapping("EsStadiumList")
    public R EsStadiumList(@RequestBody Stadium stadium, @RequestHeader(name = "token") String token){
         //模糊查询
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        if (!StringUtils.isEmpty(stadium.getStadiumName())){
            boolQueryBuilder.must(QueryBuilders.matchQuery("stadiumName",stadium.getStadiumName()));
        }

        //高亮查询
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("stadiumName").preTags("<font color='red'>").postTags("</font>");

        //进行分页
        int pageNum = 0;
        if (stadium.getPageNum()>0){
            pageNum = stadium.getPageNum()-1;
        }
        PageRequest of = PageRequest.of(pageNum, stadium.getPageSize());

        //进行分权
        Claims body = Jwts.parser().setSigningKey("bw".getBytes()).parseClaimsJws(token).getBody();
        Integer uid = body.get("uid", Integer.class);
        Integer rid = body.get("rid", Integer.class);
        if (rid!=1){
            boolQueryBuilder.must(QueryBuilders.matchQuery("userId",uid));
        }

        //组合查询
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder)
                .withHighlightBuilder(highlightBuilder)
                .withPageable(of);

        SearchHits<EsStadium> search = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), EsStadium.class);
        long total = search.getTotalHits();
        ArrayList<EsStadium> list = new ArrayList<>();
        for (SearchHit<EsStadium> esStadiumSearchHit : search) {
            EsStadium content = esStadiumSearchHit.getContent();
            List<String> stadiumName = esStadiumSearchHit.getHighlightField("stadiumName");
            if (stadiumName!=null && stadiumName.size()>0){
                String s = stadiumName.get(0);
                content.setStadiumName(s);
            }
            list.add(content);
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("total",total);
        map.put("list",list);
        map.put("pageNum",pageNum);
        map.put("pageSize",stadium.getPageSize());
        return R.OK(map);
    }

    //下拉框接口
    @PostMapping("typeList")
    public R typeList(){
        List<Type> list = typeService.list();
        return R.OK(list);
    }

    //添加
     @PostMapping("addStadium")
     public R addStadium(@RequestBody Stadium stadium,@RequestHeader(name = "token") String token){
         Claims body = Jwts.parser().setSigningKey("bw".getBytes()).parseClaimsJws(token).getBody();
         Integer uid = body.get("uid", Integer.class);
         stadium.setUserId(uid);
         stadiumService.save(stadium);
         List<Image> imageList = stadium.getImageList();
         for (Image image : imageList) {
             image.setStadiumId(stadium.getId());
             imageService.save(image);
         }
         return R.OK();
     }

     //预约页面
    @PostMapping("bookingList")
    public R bookingList(){
       List<Booking> bookings = bookingService.bookingList();
       return R.OK(bookings);
    }

    @PostMapping("linkageList")
    public R linkageList(){
        List<Linkage> list = linkageService.list();
        return R.OK(list);
    }

    @PostMapping("linkageAdd")
    public R linkageAdd(@RequestBody Booking booking){
        bookingService.save(booking);
        MessageVo messageVo = new MessageVo();
        String msgId = UUID.randomUUID().toString();
        messageVo.setMsgId(msgId);
        messageVo.setMsgBody(String.valueOf(booking));
        stringRedisTemplate.opsForValue().set(msgId, String.valueOf(booking),15, TimeUnit.MINUTES);
        rabbitTemplate.convertAndSend("directExchange","", JSON.toJSONString(messageVo));
        return R.OK();
    }

    @RabbitListener(queues = "tianjiaQueue")
    public void queue(String msg,Message message, Channel channel) throws IOException, TemplateException {

        MessageVo messageVo = JSON.parseObject(msg, MessageVo.class);
        String msgId = messageVo.getMsgId();
        String msgBody = messageVo.getMsgBody();
        List<Booking> list = bookingService.bookingList();
        HashMap<String, Object> map = new HashMap<>();
        map.put("list",list);
        String outFile = "C:\\Users\\14867\\Desktop\\FreeMarker"+UUID.randomUUID().toString()+".html";
        FreemarkerUtil freemarkerUtil = new FreemarkerUtil();
        freemarkerUtil.createHtml(map,"booking",outFile);
        if (!stringRedisTemplate.hasKey(msgId)){
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);
            return;
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);
        stringRedisTemplate.delete(msgId);
    }

    @PostConstruct
    public void hui(){
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            @Override
            public void returnedMessage(Message message, int i, String s, String s1, String s2) {
                rabbitTemplate.convertAndSend(s,s1,message);
                System.out.println("失败");
            }
        });
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean b, String s) {
                if (b){
                    System.out.println("成功");
                }else {
                    System.out.println("失败");
                }
            }
        });
    }



}
